/**
 * 
 */
package com.demo2do.strawberry.service.impl;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.encoding.Md5PasswordEncoder;
import org.springframework.stereotype.Service;

import com.demo2do.core.BusinessException;
import com.demo2do.core.persistence.GenericDaoSupport;
import com.demo2do.core.redis.GenericRedisSupport;
import com.demo2do.strawberry.Constant;
import com.demo2do.strawberry.dao.UserDao;
import com.demo2do.strawberry.entity.investor.Institution;
import com.demo2do.strawberry.entity.investor.Investor;
import com.demo2do.strawberry.entity.user.UserAccount;
import com.demo2do.strawberry.entity.user.UserRegister;
import com.demo2do.strawberry.entity.user.member.Member;
import com.demo2do.strawberry.entity.user.member.MemberTask;
import com.demo2do.strawberry.entity.user.profile.Profile;
import com.demo2do.strawberry.service.InvestorService;

/**
 * @author Downpour
 */
@Service("investorService")
public class InvestorServiceImpl implements InvestorService {
	
	@Value("#{redis['redis.investor.latest.size']}")
	private int investorLatestSize;
	
	@Autowired
	private GenericDaoSupport genericDaoSupport;
	
	@Autowired
	private GenericRedisSupport genericRedisSupport;

	@Autowired
	private UserDao userDao;

	private Md5PasswordEncoder passwordEncoder = new Md5PasswordEncoder();

	/* (non-Javadoc)
	 * @see com.demo2do.strawberry.service.InvestorService#load(java.lang.Long)
	 */
	public Investor load(Long id) {
		return genericDaoSupport.load(Investor.class, id);
	}

	/* (non-Javadoc)
	 * @see com.demo2do.strawberry.service.InvestorService#createInvestor(com.demo2do.strawberry.entity.user.member.Member, com.demo2do.strawberry.entity.user.UserRegister, com.demo2do.strawberry.entity.investor.Institution, java.lang.String, java.lang.String)
	 */
	public void createInvestor(Member member, UserRegister userRegister, Institution institution, String name, String businessCard) {
		
		// check duplication
		List<UserRegister> userRegisters = userDao.getUserRegister(userRegister.getEmail(), false);
		if(CollectionUtils.isNotEmpty(userRegisters)) {
			throw new BusinessException("error.member.create.duplication.failure", "forward:/signup?institution=" + institution.getId());
		}
		
		// 1. save member
		genericDaoSupport.save(member);
		
		// 2. save UserRegister
		String encodedPassword = passwordEncoder.encodePassword(userRegister.getPassword(), null);
		genericDaoSupport.save(userRegister.initialize(member, encodedPassword));
		
		// 3. save MemberProfile
		Profile profile = new Profile(userRegister.getEmail(), name, Constant.DEFAULT_MEMBER_AVATAR, member);
		genericDaoSupport.save(profile);
		
		// 4. save Investor
		genericDaoSupport.save(new Investor(businessCard, institution, profile, member));
		
		// 5. save MemberTask
		genericDaoSupport.save(new MemberTask(member.getId()));
		
		// 6. save UserAccount
		genericDaoSupport.save(new UserAccount(member));
		
	}
	
	/* (non-Javadoc)
	 * @see com.demo2do.strawberry.service.InvestorService#getLatestInvestors()
	 */
	@SuppressWarnings("unchecked")
	public List<Investor> getLatestInvestors() {
		
		List<String> investorIds = genericRedisSupport.getMembersForList(Constant.REDIS_INVESTOR_LATEST);
		
		List<Investor> investors = null;
		if(CollectionUtils.isNotEmpty(investorIds)) {
			investors = new ArrayList<Investor>();
			
			for(String id : investorIds) {
				Investor investor = genericDaoSupport.load(Investor.class, Long.valueOf(id));
				investors.add(investor);
			}
		} else {
			
			String query = "SELECT investor From Investor investor, UserRegister userRegister WHERE investor.member = userRegister.member AND userRegister.enabled = true ORDER BY investor.id DESC";
			List<Investor> allInvestors = genericDaoSupport.searchForList(query, Collections.EMPTY_MAP);
			investors = allInvestors.size() > investorLatestSize ? allInvestors.subList(0, investorLatestSize) : allInvestors;
			
			// add to redis latest investor list
			for(Investor investor : investors) {
				genericRedisSupport.addMembersToList(Constant.REDIS_INVESTOR_LATEST, investor.getId().toString());
			}
			
		}
		
		return investors;
	}

}
